home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*_________________________________________________________________________
- |
- | blixvect.c - functions to support operations on vectors and matrices.
- |
- | Lots of original code from David Ciemiewicz, Mark Grossman, Henry Moreton,
- | Paul Haeberli, and Gavin Bell.
- |
- | Frans van Hoesel added more specific prototypes,
- | and some functions (not all tested)
- |
- */
-
- #include <malloc.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <bstring.h>
- #include "blixvect.h"
- #include "mymath.h"
-
-
- Matrix idmatrix =
- {
- { 1.0, 0.0, 0.0, 0.0,},
- { 0.0, 1.0, 0.0, 0.0,},
- { 0.0, 0.0, 1.0, 0.0,},
- { 0.0, 0.0, 0.0, 1.0,},
- };
-
- float x_axis[] = { 1.0, 0.0, 0.0 };
- float y_axis[] = { 0.0, 1.0, 0.0 };
- float z_axis[] = { 0.0, 0.0, 1.0 };
-
-
-
- float *vnew(void) {
-
- return ( (float *) malloc(3 * sizeof(float)));
- }
-
- float *vclone(const float v[3]) {
- register float *c;
-
- c = vnew();
- vcopy(v, c);
- return c;
- }
-
- void vcopy(const float v1[3], float v2[3]) {
- v2[X] = v1[X];
- v2[Y] = v1[Y];
- v2[Z] = v1[Z];
- }
-
- void vcopy4(const float v1[4], float v2[4]) {
- v2[X] = v1[X];
- v2[Y] = v1[Y];
- v2[Z] = v1[Z];
- v2[W] = v1[W];
- }
-
- void vprint(const float v[3]) {
- printf("x: %f y: %f z: %f\n",v[X],v[Y],v[Z]);
- }
-
- void vprint4(const float v[4]) {
- printf("x: %f y: %f z: %f w: %f\n",v[X],v[Y],v[Z],v[W]);
- }
-
- void vset(float v[3], const float x, const float y, const float z) {
- v[X] = x;
- v[Y] = y;
- v[Z] = z;
- }
-
- void vset4(float v[3], const float x, const float y, const float z,
- const float w) {
- v[X] = x;
- v[Y] = y;
- v[Z] = z;
- v[W] = w;
- }
-
- void vzero(float v[3]) {
- v[X] = 0.0;
- v[Y] = 0.0;
- v[Z] = 0.0;
- }
-
- void vzero4(float v[4]) {
- v[X] = 0.0;
- v[Y] = 0.0;
- v[Z] = 0.0;
- v[W] = 0.0;
- }
-
- void vnormal(float v[3]) {
- float l;
- l = sqrtf(v[X] * v[X] + v[Y] * v[Y] + v[Z] * v[Z]);
- v[X] /= l;
- v[Y] /= l;
- v[Z] /= l;
- }
-
- void vnormal2(const float v[3], float dst[3]) {
- float l;
- l = sqrtf(v[X] * v[X] + v[Y] * v[Y] + v[Z] * v[Z]);
- dst[0] = v[0] / l;
- dst[1] = v[1] / l;
- dst[2] = v[2] / l;
- }
-
- float vlength(const float v[3]) {
- return sqrtf(v[X] * v[X] + v[Y] * v[Y] + v[Z] * v[Z]);
- }
-
- void vscalar(float v[3], const float mul) {
- v[X] *= mul;
- v[Y] *= mul;
- v[Z] *= mul;
- }
-
- void vmult(const float src1[3], const float src2[3], float dst[3]) {
-
- dst[X] = src1[X] * src2[X];
- dst[Y] = src1[Y] * src2[Y];
- dst[Z] = src1[Z] * src2[Z];
- }
-
- void vadd(const float src1[3], const float src2[3], float dst[3]) {
- dst[X] = src1[X] + src2[X];
- dst[Y] = src1[Y] + src2[Y];
- dst[Z] = src1[Z] + src2[Z];
- }
-
- void vsub(const float src1[3], const float src2[3], float dst[3]) {
- dst[X] = src1[X] - src2[X];
- dst[Y] = src1[Y] - src2[Y];
- dst[Z] = src1[Z] - src2[Z];
- }
-
- void vhalf(const float v1[3], const float v2[3], float half[3]) {
- float len;
-
- vadd(v2,v1,half);
- len = vlength(half);
- if(len > 0.0001)
- vscalar(half,1.0/len);
- else
- vcopy(v1, half);
- }
-
- float vdot(const float v1[3], const float v2[3]) {
- return v1[X]*v2[X] + v1[Y]*v2[Y] + v1[Z]*v2[Z];
- }
-
- void vcross(const float v1[3], const float v2[3], float cross[3]) {
- float t0, t1;
-
- t0 = (v1[Y] * v2[Z]) - (v1[Z] * v2[Y]);
- t1 = (v1[Z] * v2[X]) - (v1[X] * v2[Z]);
- cross[Z] = (v1[X] * v2[Y]) - (v1[Y] * v2[X]);
- cross[X] = t0;
- cross[Y] = t1;
- }
-
- void vdirection(const float v1[3], const float v2[3], float dir[3]) {
- float t0, t1, t2;
- float l;
-
- t0 = v2[X] - v1[X];
- t1 = v2[Y] - v1[Y];
- t2 = v2[Z] - v1[Z];
- l = t0*t0 + t1*t1 + t2*t2;
- if (l <= 1e-9 ) {
- /* create a direction cross to v1 */
- t0 = 0;
- t1 = -v1[Z];
- t2 = v1[Y];
- l = t1*t1 + t2*t2;
- }
- /* normalize dir */
- l = sqrtf(l);
- dir[X] = t0 / l;
- dir[Y] = t1 / l;
- dir[Z] = t2 / l;
- }
-
- void vreflect(const float in[3], const float mirror[3], float out[3]) {
- float temp[3];
-
- vcopy(mirror, temp);
- vscalar(temp,vdot(mirror,in));
- vsub(temp,in,out);
- vadd(temp,out,out);
- }
-
- int veq(const float v1[3], const float v2[3]) {
- if (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
- return 1;
- else
- return 0;
- }
-
- /*
- * polar coordinates are encoded as eighter theta, phi, or as
- * theta, phi, r. The case with only theta and phi is asumed to have
- * a radius of 1.0
- *
- */
-
- void frompolar(const float p[2], float v[3]) {
- register float spt;
-
- spt = sinf(p[THETA]);
- v[X] = spt * cosf(p[PHI]);
- v[Y] = spt * sinf(p[PHI]);
- v[Z] = cosf(p[THETA]) ;
- }
-
- void frompolar3(const float p[3], float v[3]) {
- register float spt;
-
- spt = sinf(p[THETA]);
- v[X] = p[R] * spt * cosf(p[PHI]);
- v[Y] = p[R] * spt * sinf(p[PHI]);
- v[Z] = p[R] * cosf(p[THETA]) ;
- }
-
- void topolar(const float v[3], float p[2]) {
- register float t;
-
- p[THETA] = acosf(v[Z] );
- t = sqrtf(1 - SQR(v[Z]));
- if (t < 1e-5)
- p[PHI] = 0.0;
- else
- p[PHI] = atan2f(v[Y]/t, v[X]/t);
- }
-
- void topolar3(const float v[3], float p[3]) {
- register float r;
-
- r = sqrtf(SQR(v[X]) + SQR(v[Y]) + SQR(v[Z]));
- p[R] = r;
- if (r < 1e-5) {
- p[THETA] = 0.0;
- p[PHI] = 0.0;
- } else {
- p[THETA] = acosf(v[Z] / r);
- /* re-use register variable r */
- r = sqrtf(SQR(r) - SQR(v[Z]));
- if (r < 1e-5)
- p[PHI] = 0.0;
- else
- p[PHI] = atan2f(v[Y]/r, v[X]/r);
- }
- }
-
- float vdistance(const float v1[3], const float v2[3]) {
-
- return sqrtf(SQR(v1[X]-v2[X]) + SQR(v1[Y]-v2[Y]) + SQR(v1[Z]-v2[Z]));
- }
-
- float vdistance2(const float v1[3], const float v2[3]) {
-
- return SQR(v1[X]-v2[X]) + SQR(v1[Y]-v2[Y]) + SQR(v1[Z]-v2[Z]);
- }
-
- float vdistance_angle(const float p1[2], const float p2[2]) {
-
- return acos(cos(p1[THETA])*cos(p2[THETA]) +
- sin(p1[THETA])*sin(p2[THETA])*cos(p1[PHI]-p2[PHI]));
- }
-
- void mprint(const Matrix m) {
- register int row;
-
- printf("Matrix: \n");
- for (row=X; row <=W; row++)
- printf("%12f %12f %12f %12f\n", m[row][X], m[row][Y],
- m[row][Z], m[row][W]);
- }
-
- void mmultmatrix(const Matrix m1, const Matrix m2, Matrix prod) {
- register int row, col;
- Matrix temp;
-
- for(row=X ; row<=W; row++)
- for(col=X; col<=W; col++)
- temp[row][col] = m1[row][X] * m2[X][col]
- + m1[row][Y] * m2[Y][col]
- + m1[row][Z] * m2[Z][col]
- + m1[row][W] * m2[W][col];
- for(row=X ; row<=W; row++)
- for(col=X ; col<=W ; col++)
- prod[row][col] = temp[row][col];
- }
-
- void vtransform(const float v[3], const Matrix mat, float vt[3]) {
- float tx, ty;
-
- tx = v[X]*mat[X][X] + v[Y]*mat[Y][X] + v[Z]*mat[Z][X] + mat[W][X];
- ty = v[X]*mat[X][Y] + v[Y]*mat[Y][Y] + v[Z]*mat[Z][Y] + mat[W][Y];
- vt[Z] = v[X]*mat[X][Z] + v[Y]*mat[Y][Z] + v[Z]*mat[Z][Z] + mat[W][Z];
- vt[X] = tx;
- vt[Y] = ty;
- }
-
- void vtransform4(const float v[4], const Matrix mat, float vt[4]) {
- float t[4];
-
- t[X] = v[X]*mat[X][X] + v[Y]*mat[Y][X] + v[Z]*mat[Z][X] + mat[W][X];
- t[Y] = v[X]*mat[X][Y] + v[Y]*mat[Y][Y] + v[Z]*mat[Z][Y] + mat[W][Y];
- t[Z] = v[X]*mat[X][Z] + v[Y]*mat[Y][Z] + v[Z]*mat[Z][Z] + mat[W][Z];
- t[W] = v[X]*mat[X][W] + v[Y]*mat[Y][W] + v[Z]*mat[Z][W] + mat[W][W];
- vcopy4(t, vt);
- }
-
- void mcopy(const Matrix m1, Matrix m2) {
- register int i, j;
-
- for (i = X; i <= W; i++)
- for (j = X; j <= W; j++)
- m2[i][j] = m1[i][j];
- }
-
- void mbuild_polar_rot(const float p1[2], Matrix m) {
-
- m[X][X] = cosf(p1[THETA]);
- m[X][Y] = 0.0;
- m[X][Z] = sinf(p1[THETA]);
- m[X][W] = 0.0;
-
- m[Y][X] = sinf(p1[PHI]) * sinf(p1[THETA]);
- m[Y][Y] = cosf(p1[PHI]);
- m[Y][Z] = -sinf(p1[PHI]) * cosf(p1[THETA]);
- m[Y][W] = 0.0;
-
- m[Z][X] = -cosf(p1[PHI]) * sinf(p1[THETA]);
- m[Z][Y] = sinf(p1[THETA]);
- m[Z][Z] = cosf(p1[PHI]) * cosf(p1[THETA]);
- m[Z][W] = 0.0;
-
- m[W][X] = 0.0;
- m[W][Y] = 0.0;
- m[W][Z] = 0.0;
- m[W][X] = 1.0;
- }
-
- void mmake_rot_axis(const float a[3], const float alpha, Matrix m) {
-
- float q0, q1, q2, q3;
- float s;
- /* first build the quarternion */
- s = sinf(alpha/2.0) / vlength(a);
- q0 = a[X] * s;
- q1 = a[Y] * s;
- q2 = a[Z] * s;
- q3 = cosf(alpha/2.0);
- /* then build the matrix */
- m[X][X] = 1.0 - 2.0 * (q1 * q1 + q2 * q2);
- m[X][Y] = 2.0 * (q0 * q1 - q2 * q3);
- m[X][Z] = 2.0 * (q2 * q0 + q1 * q3);
- m[X][W] = 0.0;
-
- m[Y][X] = 2.0 * (q0 * q1 + q2 * q3);
- m[Y][Y] = 1.0 - 2.0 * (q2 * q2 + q0 * q0);
- m[Y][Z] = 2.0 * (q1 * q2 - q0 * q3);
- m[Y][W] = 0.0;
-
- m[Z][X] = 2.0 * (q2 * q0 - q1 * q3);
- m[Z][Y] = 2.0 * (q1 * q2 + q0 * q3);
- m[Z][Z] = 1.0 - 2.0 * (q1 * q1 + q0 * q0);
- m[Z][W] = 0.0;
-
- m[W][X] = 0.0;
- m[W][Y] = 0.0;
- m[W][Z] = 0.0;
- m[W][W] = 1.0;
- }
-
- void vrot_axis(const float v1[3], const float a[3], const float alpha,
- float v2[3]) {
- float q0, q1, q2, q3;
- float s, tx, ty;
- /* first build the quarternion */
- s = sinf(alpha/2.0) / vlength(a);
- q0 = a[X] * s;
- q1 = a[Y] * s;
- q2 = a[Z] * s;
- q3 = cosf(alpha/2.0);
- /* then calculate the new vector */
- tx = (1.0 - 2.0 * (q1 * q1 + q2 * q2)) * v1[X] +
- (2.0 * (q0 * q1 - q2 * q3)) * v1[Y] +
- (2.0 * (q2 * q0 + q1 * q3)) * v1[Z];
- ty = (2.0 * (q0 * q1 + q2 * q3)) * v1[X] +
- (1.0 - 2.0 * (q2 * q2 + q0 * q0)) * v1[Y] +
- (2.0 * (q1 * q2 - q0 * q3)) * v1[Z];
- v2[Z] = (2.0 * (q2 * q0 - q1 * q3)) * v1[X] +
- (2.0 * (q1 * q2 + q0 * q3)) * v1[Y] +
- (1.0 - 2.0 * (q1 * q1 + q0 * q0)) * v1[Z];
- v2[X] = tx;
- v2[Y] = ty;
- }
-
- /*
- * rotate normalized vector a into normalized vector b.
- * put the 4 by 4 rotation matrix in mat.
- *
- */
- void mmakerot(const float a[3], const float b[3], Matrix mat) {
- float t1[4], t2[4], t3[4];
- Matrix mat1, mat2;
- int i;
-
- vcross(b, a, t1);
- vnormal(t1);
- vcross(b,t1,t2);
- vcross(a,t1,t3);
- vnormal(t2);
- vnormal(t3);
- mat1[W][W] = mat2[W][W] = 1.0;
- for(i=X; i<=Z; i++) {
- mat1[i][W] = mat1[W][i] = mat2[i][W] = mat2[W][i] = 0.0;
- mat1[X][i] = b[i];
- mat1[Y][i] = t2[i];
- mat1[Z][i] = t1[i];
- mat2[i][X] = a[i];
- mat2[i][Y] = t3[i];
- mat2[i][Z] = t1[i];
- }
- mmultmatrix(mat1,mat2,mat);
- }
-
- void minvert(const Matrix mat, Matrix result) {
- int i, j, k;
- double temp;
- double m[8][4];
- /* Declare identity matrix */
-
- mcopy(idmatrix, result);
- for (i = X; i <= W; i++) {
- for (j = X; j <= W; j++) {
- m[i][j] = mat[i][j];
- m[i+4][j] = result[i][j];
- }
- }
-
- /* Work across by columns */
-
- for (i = X; i <= W; i++) {
- for (j = i; (m[i][j] == 0.0) && (j <= W); j++) {
- ;; /* avoid warning empty for */
- }
- if (j == 4) {
- fprintf (stderr, "error: cannot do inverse matrix\n");
- exit (2);
- }
- else if (i != j) {
- for (k = 0; k < 8; k++) {
- temp = m[k][i];
- m[k][i] = m[k][j];
- m[k][j] = temp;
- }
- }
-
- /* Divide original row */
-
- for (j = 7; j >= i; j--)
- m[j][i] /= m[i][i];
-
- /* Subtract other rows */
-
- for (j = X; j <= W; j++)
- if (i != j)
- for (k = 7; k >= i; k--)
- m[k][j] -= m[k][i] * m[i][j];
- }
-
- for (i = X; i <= W; i++)
- for (j = X; j <= W; j++)
- result[i][j] = m[i+4][j];
- }
-
- /*
- * Get combined Model/View/Projection matrix, in any mmode
- */
- void mgetmatrix(Matrix m) {
- long mm;
-
- mm = getmmode();
-
- if (mm == MSINGLE)
- {
- getmatrix(m);
- }
- else
- {
- Matrix mp, mv;
-
- mmode(MPROJECTION);
- getmatrix(mp);
- mmode(MVIEWING);
- getmatrix(mv);
-
- pushmatrix(); /* Multiply them together */
- loadmatrix(mp);
- multmatrix(mv);
- getmatrix(m);
- popmatrix();
-
- mmode((short)mm); /* Back into the mode we started in */
- }
- }
-
- /*
- * Gaussian Elimination with Scaled Column Pivoting
- *
- * copied out of the book by Wade Olsen
- * Silicon Graphics
- * Feb. 12, 1990
- */
-
- void linsolve(
- const float *eqs[], /* System of eq's to solve */
- int n, /* of size inmat[n][n+1] */
- float *x /* Result float *or of size x[n] */
- )
- {
- int i, j, p;
-
- float **a;
-
- /* Allocate space to work in */
- /* (avoid modifying the equations passed) */
- a = (float **)malloc(sizeof(float *)*n);
- for (i = 0; i < n; i++)
- {
- a[i] = (float *)malloc(sizeof(float)*(n+1));
- bcopy(eqs[i], a[i], sizeof(float)*(n+1));
- }
-
-
- if (n == 1) { /* The simple single variable case */
- x[0] = a[0][1] / a[0][0];
- return;
- }
- /* Gausian elimination process */
- for (i = 0; i < n -1; i++) {
- /* find non-zero pivot row */
- p = i;
- while (a[p][i] == 0.0) {
- p++;
- if (p == n) {
- printf("linsolv: No unique solution exists.\n");
- exit(1);
- }
- }
- /* row swap */
- if (p != i) {
- float *swap;
-
- swap = a[i];
- a[i] = a[p];
- a[p] = swap;
- }
- /* row subtractions */
- for (j = i + 1; j < n; j++) {
- float mult = a[j][i] / a[i][i];
-
- int k;
- for (k = i + 1; k < n + 1; k++)
- a[j][k] -= mult * a[i][k];
- }
- }
-
- if (a[n-1][n-1] == 0.0) {
- printf("linsolv: No unique solution exists.\n");
- exit(1);
- }
-
- /* backwards substitution */
- x[n-1] = a[n-1][n] / a[n-1][n-1];
- for (i = n -2; i > -1; i--) {
- float sum = a[i][n];
-
- for (j = i + 1; j < n; j++)
- sum -= a[i][j] * x[j];
-
- x[i] = sum / a[i][i];
- }
-
- /* Free working space */
- for (i = 0; i < n; i++)
- {
- free(a[i]);
- }
- free(a);
- }
-